/********************************************************************************
*                                                                               *
* kWookaApplicationListPanel.cpp -- Show application list  for a project        *
*                                                                               *
* Copyright (c) Fengren Technology(Guangzhou) Co.LTD. All rights reserved.      *
*                                                                               *
********************************************************************************/


#include "kWookaApplicationListPanel.hpp"

#include "kWooka_ids.h"
#include "kWookaApplicationItemPanel.hpp"
#include <wx/filesys.h>
#include <wx/zipstrm.h>
#include <wx/wfstream.h>
#include <wx/txtstrm.h>
#include <wx/arrimpl.cpp>
#include "wx/metafile.h"
#include "wx/artprov.h"
#include "kWooka_perferences_utils.hpp"
#include "kWookaApplicationNginxServerPanel.hpp"

WX_DEFINE_OBJARRAY(kWookaApplicationItemArray);


BEGIN_EVENT_TABLE(kWookaApplicationListPanel, wxPanel)
    ////Manual Code Start
    EVT_BUTTON(ID_WXBUTTON_ADDAPP, kWookaApplicationListPanel::OnAddApp)
    EVT_BUTTON(ID_WXBUTTON_STARTALL, kWookaApplicationListPanel::OnStartAll)
    EVT_BUTTON(ID_WXBUTTON_STOPALL, kWookaApplicationListPanel::OnStopApps)
    EVT_BUTTON(ID_WXBUTTON_ADDMORE, kWookaApplicationListPanel::OnAddMore)
    EVT_MENU(ID_MENU_NGINX_SERVER, kWookaApplicationListPanel::OnMenu)
    EVT_MENU(ID_MENU_NGINX_SERVICE, kWookaApplicationListPanel::OnMenu)
    EVT_MENU(ID_MENU_MYSQL, kWookaApplicationListPanel::OnMenu)
    EVT_MENU(ID_MENU_REDIS, kWookaApplicationListPanel::OnMenu)
    EVT_MENU(ID_MENU_GENERIC_JAVA, kWookaApplicationListPanel::OnMenu)
    EVT_MENU(ID_MENU_MAVEN, kWookaApplicationListPanel::OnMenu)
    EVT_THREAD(EVT_UPDATE_EXECUTE_STATE, kWookaApplicationListPanel::OnUpdateExecuteState)
    EVT_END_PROCESS(ID_THREAD_EVENT_PROCESS_END, kWookaApplicationListPanel::OnProcessEnded)
    ////Manual Code End
    //EVT_KEY_DOWN(kPosSimpleCheckoutPanel::OnKeyCharEvent)
END_EVENT_TABLE()



kWookaApplicationListPanel::kWookaApplicationListPanel(wxWindow *parent, wxWindowID id, const wxString& WXUNUSED(title), const wxPoint &position, const wxSize& size, long style)
: wxPanel(parent, id, position, size, style)
{
    m_project = NULL;
    SetBackgroundColour(COLOURE_LEAVE_WINDOW);
    
    CreateGUIControls();
}

kWookaApplicationListPanel::~kWookaApplicationListPanel()
{
    wxLogDebug(wxT("kWookaApplicationListPanel destroyed."));
}

void kWookaApplicationListPanel::CreateGUIControls()
{
    //Do not add custom code between
    //GUI Items Creation Start and GUI Items Creation End
    //wxDev-C++ designer will remove them.
    //Add the custom code before or after the blocks
    ////GUI Items Creation Start

    CreateSearchPanel();
    Center();

    ////GUI Items Creation End
}

/**
    Create the Search panel
    1. Status, 2. Order No, 3. Order Name, 4. Pay Time
 */
void kWookaApplicationListPanel::CreateSearchPanel() {
    wxBoxSizer* wxBarcodeBoxSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* wxVertBoxSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* wxHorzBoxSizer = new wxBoxSizer(wxHORIZONTAL);

    wxScrolledWindow* scrollWindow = new wxScrolledWindow(this);
    
    WxBtnAddApp = new wxButton(this, ID_WXBUTTON_ADDAPP, _("Add Spring Boot Application"), wxPoint(500, 270), wxSize(320, 32), 0, wxDefaultValidator, _T("WxButton1"));
    WxBtnAddMore = new wxBitmapButton(this, ID_WXBUTTON_ADDMORE, wxArtProvider::GetBitmap(wxART_PLUS), wxPoint(500, 270), wxSize(36, 36), 0, wxDefaultValidator, _T("WxButton1"));
    //WxBtnStartAll = new wxButton(this, ID_WXBUTTON_STARTALL, _("Start All"), wxPoint(500, 270), wxSize(145, 45), 0, wxDefaultValidator, _T("WxButton2"));
    //WxBtnStopAll = new wxButton(this, ID_WXBUTTON_STOPALL, _("Stop All"), wxPoint(500, 270), wxSize(145, 45), 0, wxDefaultValidator, _T("WxButton3"));
    
    wxHorzBoxSizer->Add(WxBtnAddApp, 1, wxEXPAND | wxALL, 0);
    wxHorzBoxSizer->Add(WxBtnAddMore, 0, wxSTRETCH_NOT | wxRIGHT, 0);
    //wxHorzBoxSizer->Add(WxBtnStartAll, 0, wxEXPAND | wxALL, 5);
    //wxHorzBoxSizer->Add(WxBtnStopAll, 0, wxEXPAND | wxALL, 5);
    wxBarcodeBoxSizer->Add(wxHorzBoxSizer, 0, wxEXPAND | wxALIGN_TOP | wxALL, 5);

    WxBtnAddApp->Disable();
    WxBtnAddMore->Disable();

    scrollWindow->SetSizerAndFit(wxVertBoxSizer);
    scrollWindow->SetScrollbars(1, 1, 400, 600);
    
    wxBarcodeBoxSizer->Add(scrollWindow, 5, wxEXPAND | wxTOP, 5);
    wxSizer = wxBarcodeBoxSizer;
    m_scrollWindow = scrollWindow;
    m_scrollWindow->SetBackgroundColour(COLOURE_LEAVE_WINDOW);
    m_wxVertBoxSizer = wxVertBoxSizer;

    this->SetSizerAndFit(wxSizer);
}

void kWookaApplicationListPanel::OnKeyCharEvent(wxKeyEvent& event){
    if (event.GetKeyCode() == WXK_RETURN){
    }
}


void kWookaApplicationListPanel::SetProjectInfo(kWookaProjectInfo* project) {
    this->m_project = project;
    this->UpdatePanels();
}

const kWookaProjectInfo* kWookaApplicationListPanel::GetProjectInfo() const {
    return this->m_project;
}

void kWookaApplicationListPanel::RemoveItemPanel(kWookaApplicationItemPanel* item) {
    // int idx = this->m_itempanels.Index(item);
    kWookaApplicationItemPanel* that = dynamic_cast<kWookaApplicationItemPanel*>(item);
    for (size_t st = 0; st < m_itempanels.Count(); st++) {
        kWookaApplicationItemPanel* pnl = dynamic_cast<kWookaApplicationItemPanel*>(m_itempanels[st]);
        if (pnl == that) {
            m_itempanels.RemoveAt(st);
            m_wxVertBoxSizer->Remove(item->GetSizer());
            m_scrollWindow->RemoveChild(pnl);
            delete pnl;
            m_scrollWindow->Layout();
            break;
        }
    }

}

void kWookaApplicationListPanel::OnAddApp(wxCommandEvent& WXUNUSED(event)) {

    if (m_project == NULL) {
        return;
    }

    wxFileDialog fd(this, _("Open a SpringBoot application"), wxEmptyString, wxEmptyString, _("SpringBoot Fat JAR (*.jar)|*.jar|" "All files (*.*)|*.*"));
    wxString filenameWin("META-INF\\MANIFEST.MF");
    wxString filenameUnix("META-INF/MANIFEST.MF");

    if (fd.ShowModal() == wxID_OK) {
        wxString fl = fd.GetPath();
        wxFileInputStream in(fl);
        wxZipInputStream zip(in);
        wxZipEntry* entry = zip.GetNextEntry();
        while (entry != NULL)
        {
            wxString name = entry->GetName();
            wxFileName fname(name);
            wxString FilePath = fname.GetPath();
            if (name == filenameWin || name == filenameUnix) {
                // here to parse the file
                wxTextInputStream txt(zip);
                kWookaAppItemInfo appitem;
                appitem.source = fl;
                appitem.id = wxNewGuid();
                appitem.appType = wxT("springboot");
                wxString line = txt.ReadLine();
                while (line.IsNull() == false) {
                    wxString nextline = txt.ReadLine();
                    if (line.StartsWith("Implementation-Title:")) {
                        appitem.name = line.SubString(wxString("Implementation-Title:").Length(), line.Length()).Trim().Trim(false);
                        if (nextline.IsNull() == false && nextline.Find(wxString(":")) == -1){
                            appitem.name += nextline.Trim().Trim(false);
                            nextline = txt.ReadLine();
                        }
                    } else if (line.StartsWith("Implementation-Version:")) {
                        appitem.version = line.SubString(wxString("Implementation-Version:").Length(), line.Length()).Trim().Trim(false);
                        if (nextline.IsNull() == false && nextline.Find(wxString(":")) == -1) {
                            appitem.version += nextline.Trim().Trim(false);
                            nextline = txt.ReadLine();
                        }
                    } else if (line.StartsWith("Implementation-Vendor-Id:")) {
                        appitem.groupId = line.SubString(wxString("Implementation-Vendor-Id:").Length(), line.Length()).Trim().Trim(false);
                        if (nextline.IsNull() == false && nextline.Find(wxString(":")) == -1) {
                            appitem.groupId += nextline.Trim().Trim(false);
                            nextline = txt.ReadLine();
                        }
                    } else if (line.StartsWith("Start-Class:")) {
                        appitem.startClass = line.SubString(wxString("Start-Class:").Length(), line.Length()).Trim().Trim(false);
                        if (nextline.IsNull() == false && nextline.Find(wxString(":")) == -1) {
                            appitem.startClass += nextline.Trim().Trim(false);
                            nextline = txt.ReadLine();
                        }
                    }

                    line = nextline;
                }
                delete entry;

                if (!appitem.name.IsEmpty() && !appitem.groupId.IsEmpty() && !appitem.startClass.IsEmpty()) {
                    m_project->AddAppItem(appitem);
                    this->UpdatePanels();
                }
                break;
            }

            //    Implementation - Title: chimes - ac - auth
            //    Implementation - Version : 1.2.0 - SNAPSHOT
            //    Built - By : mekot
            //    Implementation - Vendor - Id : com.kiloseed.chimes
            //    Start - Class : com.kiloseed.ac.auth.ChimesAcAuthApplication
            delete entry;
            entry = zip.GetNextEntry();
        }
    }
}

void kWookaApplicationListPanel::StartAllApps() {
    for (size_t s = 0; s < m_itempanels.Count(); s++) {
        kWookaApplicationItemPanel* pnl = m_itempanels[s];
        wxCommandEvent ce(wxEVT_BUTTON);
        ce.SetId(kWookaApplicationItemPanel::ID_WXBUTTON_STARTAPP);
        wxQueueEvent(pnl, ce.Clone());
    }
}

void kWookaApplicationListPanel::StopAllApps() {
    for (size_t s = 0; s < m_itempanels.Count(); s++) {
        kWookaApplicationItemPanel* pnl = m_itempanels[s];
        wxCommandEvent ce(wxEVT_BUTTON);
        ce.SetId(kWookaApplicationItemPanel::ID_WXBUTTON_STOPAPP);
        wxQueueEvent(pnl, ce.Clone());
    }
}

void kWookaApplicationListPanel::OnStartAll(wxCommandEvent& WXUNUSED(event)) {
    StartAllApps();
}

void kWookaApplicationListPanel::OnStopApps(wxCommandEvent& WXUNUSED(event)) {
    StopAllApps();
}

void kWookaApplicationListPanel::OnProcessEnded(wxProcessEvent& evnt) {
    long pid = evnt.GetPid();
    for (size_t s = 0; s < m_itempanels.Count(); s++) {
        kWookaApplicationItemPanel* pnl = m_itempanels[s];
        kWookaProcessExecutor* pe = pnl->GetExecutor();
        if (pe != NULL) {
            if (pid == pe->GetPid()) {
                pnl->UpdateButtonState();
            }
        }
    }
}

/// <summary>
/// 根据m_project->Applications来生成与之对应的Panels，并进行展示
/// </summary>
void kWookaApplicationListPanel::UpdatePanels() {
    for (size_t s = 0; s < this->m_itempanels.Count(); s++) {
        kWookaApplicationItemPanel* panel = this->m_itempanels[s];
        m_scrollWindow->RemoveChild(panel);
        delete panel;
    }
    m_wxVertBoxSizer->Clear();
    m_scrollWindow->Layout();
    m_itempanels.Clear();
    WxBtnAddApp->Disable();
    WxBtnAddMore->Disable();
    
    if (m_project != NULL) {
        for (size_t i = 0;i < m_project->Applications.Count(); i++) {
            kWookaAppItemInfo& item = m_project->Applications[i];
            kWookaApplicationItemPanel* itemPanel = new kWookaApplicationItemPanel(m_scrollWindow, wxID_ANY + i);
            itemPanel->SetAppItemInfo(&item);
            itemPanel->SetProjectInfo(m_project);
            itemPanel->SetListPanel(this);
            itemPanel->SetBackgroundColour(GetBackgroundColour());
            m_wxVertBoxSizer->Add(itemPanel, 0, wxEXPAND | wxCENTER | wxTOP, 5);
            this->m_itempanels.Add(itemPanel);
        }
        WxBtnAddApp->Enable(true);
        WxBtnAddMore->Enable(true);
    }
    m_scrollWindow->Layout();
    this->Refresh();
    this->Layout();
}


void kWookaApplicationListPanel::SetWookaFrame(kWookaFrame* lf) {
    m_wookaframe = lf;
}

kWookaFrame* kWookaApplicationListPanel::GetWookaFrame() {
    return m_wookaframe;
}


void kWookaApplicationListPanel::UpdateSelectItem(kWookaApplicationItemPanel* item) {
    for (size_t s = 0; s < m_itempanels.Count(); s++) {
        kWookaApplicationItemPanel* pnl = m_itempanels[s];
        if (pnl == item) {
            pnl->SetSelected(item->IsSelected());
        }
        else {
            if (pnl != NULL) {
                pnl->SetSelected(false);
            }
        }
    }
    Refresh();
}

void kWookaApplicationListPanel::OnUpdateExecuteState(wxThreadEvent& event) {
    for (size_t s = 0; s < m_itempanels.Count(); s++) {
        kWookaApplicationItemPanel* pnl = m_itempanels[s];
        wxQueueEvent(pnl, event.Clone());
    }
    event.UnRef();
}

void kWookaApplicationListPanel::OnAddMore(wxCommandEvent& event) {
    wxMenu contextMenu;
    wxMenuItem* menuItemNgxServer = new wxMenuItem(&contextMenu, ID_MENU_NGINX_SERVER, _("Add nginx Server Configuration"));
    // wxMenuItem* menuItemNgxService = new wxMenuItem(&contextMenu, ID_MENU_NGINX_SERVICE, _("Add nginx Service Configuration"));
    wxMenuItem* menuItemMySQL = new wxMenuItem(&contextMenu, ID_MENU_MYSQL, _("Add MySQL Database"));
    wxMenuItem* menuItemRedis = new wxMenuItem(&contextMenu, ID_MENU_REDIS, _("Add Redis Cache Support"));
    wxMenuItem* menuItemMaven = new wxMenuItem(&contextMenu, ID_MENU_MAVEN, _("Add Maven Application"));
    wxMenuItem* menuItemJava = new wxMenuItem(&contextMenu, ID_MENU_GENERIC_JAVA, _("Add Generic Java Application"));
    contextMenu.Append(menuItemNgxServer);
    // contextMenu.Append(menuItemNgxService);
    contextMenu.Append(menuItemMySQL);
    contextMenu.Append(menuItemRedis);
    contextMenu.Append(menuItemMaven);
    contextMenu.Append(menuItemJava);
    wxPoint pt = this->WxBtnAddMore->GetPosition();
    wxSize  sz = this->WxBtnAddMore->GetSize();
    pt.y = pt.y + sz.y;
    this->PopupMenu(&contextMenu, pt);
}

void kWookaApplicationListPanel::OnMenu(wxCommandEvent& event) {
    kWookaAppItemInfo appitem;
    appitem.id = wxNewGuid();
    switch (event.GetId()) {
    case ID_MENU_NGINX_SERVER:
        appitem.source = wxT("");
        appitem.name = wxT("NGINX Server");
        appitem.version = wxT("1.0.0");
        appitem.appType = wxT("nginx-server");
        break;
    case ID_MENU_NGINX_SERVICE:
        appitem.source = wxT("<<nginx http service>>");
        appitem.name = wxT("<<nginx http service>>");
        appitem.appType = wxT("nginx-service");
        break;
    case ID_MENU_MYSQL:
        appitem.name = wxT("MySQL");
        appitem.source = wxT("MySQL Database");
        appitem.appType = wxT("mysql");
        break;
    case ID_MENU_REDIS:
        appitem.name = wxT("Redis");
        appitem.source = wxT("Redis Cache Support");
        appitem.appType = wxT("redis");
        break;
    case ID_MENU_MAVEN:
        appitem.source = wxT("MavenApplication");
        appitem.name = wxT("Maven Application");
        appitem.appType = wxT("maven");
        break;
    case ID_MENU_GENERIC_JAVA:
        appitem.name = wxT("Generic Java Application");
        appitem.source = wxT("<<Generic Java Application>>");
        appitem.appType = wxT("java");
        break;
    default:
        return;
    }
    if (m_project != NULL) {
        m_project->AddAppItem(appitem);
        this->UpdatePanels();
    }
}